﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Miko.CS.Net;

namespace Socket_Client
{
    public partial class Form_SendFile : Form
    {
        const string FontName = "Microsoft YaHei";

        FileList markedList = FileList.None;
        FileState markedState = FileState.None;
        long markedFileID = 0;

        Form_Client form;
        Timer timer;

        StringFormat format;
        StringFormat formatCenter;

        Bitmap play;
        Bitmap pause;
        Bitmap abort;

        const int ListHeight = 60;
        const int FileNameHeight = 22;
        const int InfoPointY = 21;
        const int StatePointY = 35;
        const int InfoHeight = 18;
        const int ProgressHeight = 5;
        const int MinWidth = 200;
        const int Blank = 3;
        const int IconSize = 48;
        const int PlaySize = 24;

        public Form_SendFile()
        {
            InitializeComponent();
        }

        private void btnChooseFiles_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Multiselect = true;
            if (fileDialog.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            foreach (var t in fileDialog.FileNames)
            {
                try
                {
                    form.Client.SendFile(form.markedID, t);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, ex.Message, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        private void Form_SendFile_Load(object sender, EventArgs e)
        {
            if (Owner == null || Owner.GetType() != typeof(Form_Client))
            {
                throw new ArgumentException("父对象无效或不存在!");
            }
            form = (Form_Client)Owner;

            //abort = Properties.Resources.Abort;
            //play = Properties.Resources.Continue;
            //pause = Properties.Resources.Pause;

            timer = new Timer();
            timer.Interval = 500;
            timer.Tick += Timer_Tick;
            timer.Start();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            form.Client.CleanFileList();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            draw();
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            draw(e.X, e.Y);

            int x = e.X;
            int y = e.Y % ListHeight;

            int width = pictureBox1.Width;

            Rectangle rectPlay = new Rectangle(width - Blank - PlaySize * 2, Blank + PlaySize, PlaySize, PlaySize);
            Rectangle rectAbort = new Rectangle(width - Blank - PlaySize, Blank + PlaySize, PlaySize, PlaySize);

            // 绘制按钮
            if (markedState != FileState.Aborted && markedState != FileState.Completed)
            {
                if (x > rectAbort.X && y > rectAbort.Y && x < rectAbort.Right && y < rectAbort.Bottom)
                {
                    form.Client.FileAbort(markedList, markedFileID);
                }
                if (x > rectPlay.X && y > rectPlay.Y && x < rectPlay.Right && y < rectPlay.Bottom)
                {
                    if (markedState == FileState.Transing)
                    {
                        form.Client.FilePause(markedList, markedFileID);
                    }
                    else
                    {
                        form.Client.FileContinue(markedList, markedFileID);
                    }
                }
            }
        }

        void draw(int x = -1, int y = -1)
        {
            ClientFile[] listSourceFile;
            ClientFile[] listTargetFile;

            lock (form.Client.ListSourceFile)
            {
                listSourceFile = new ClientFile[form.Client.ListSourceFile.Count];
                form.Client.ListSourceFile.CopyTo(listSourceFile);
            }
            lock (form.Client.ListTargetFile)
            {
                listTargetFile = new ClientFile[form.Client.ListTargetFile.Count];
                form.Client.ListTargetFile.CopyTo(listTargetFile);
            }

            int count = listSourceFile.Length + listTargetFile.Length;
            if (count <= 0)
            {
                if (pictureBox1.Image != null)
                {
                    markedList = FileList.None;
                    markedFileID = 0;

                    Image temp = pictureBox1.Image;
                    pictureBox1.Image = null;
                    temp.Dispose();
                }

                pictureBox1.Size = new Size(0, 0);
                return;
            }

            if (x >= 0 && y >= 0)
            {
                markedList = FileList.None;
                markedState = FileState.None;
                markedFileID = 0;

                int selecID = y / ListHeight;

                if (selecID < listSourceFile.Length)
                {
                    markedList = FileList.Source;
                    markedState = listSourceFile[selecID].State;
                    markedFileID = listSourceFile[selecID].FileID;
                }
                else if (selecID < listSourceFile.Length + listTargetFile.Length)
                {
                    markedList = FileList.Target;
                    markedState = listTargetFile[selecID - listSourceFile.Length].State;
                    markedFileID = listTargetFile[selecID - listSourceFile.Length].FileID;
                }
            }

            int width = (panel1.Width - 2 > MinWidth) ? panel1.Width - 2 : MinWidth;
            int height = count * ListHeight;

            if (height > panel1.Height - 2)
            {
                width -= SystemInformation.VerticalScrollBarWidth;
            }

            Bitmap bitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bitmap);
            g.Clear(Color.White);

            for (int i = 0; i < listSourceFile.Length + listTargetFile.Length; i++)
            {
                int pointY = i * ListHeight;

                ClientFile clientFile = (i < listSourceFile.Length) ? listSourceFile[i] : listTargetFile[i - listSourceFile.Length];

                Rectangle rectIcon = new Rectangle(Blank, pointY + Blank, IconSize, IconSize);
                Rectangle rectName = new Rectangle(Blank + IconSize, pointY + Blank, (width - 3 * Blank - IconSize), FileNameHeight);
                Rectangle rectInfo = new Rectangle(Blank + IconSize, pointY + InfoPointY, (width - 2 * Blank - IconSize - PlaySize * 2), InfoHeight);
                Rectangle rectState = new Rectangle(Blank + IconSize, pointY + StatePointY, (width - 2 * Blank - IconSize - PlaySize * 2), InfoHeight);

                Rectangle rectPlay = new Rectangle(width - Blank - PlaySize * 2, pointY + Blank + PlaySize, PlaySize, PlaySize);
                Rectangle rectAbort = new Rectangle(width - Blank - PlaySize, pointY + Blank + PlaySize, PlaySize, PlaySize);

                // 绘制按钮
                if (clientFile.State != FileState.Aborted && clientFile.State != FileState.Completed)
                {
                    g.DrawImage(abort, rectAbort);
                    if (clientFile.State == FileState.Transing)
                    {
                        g.DrawImage(pause, rectPlay);
                    }
                    else
                    {
                        g.DrawImage(play, rectPlay);
                    }
                }

                // 绘制文件名和用户 ID
                g.DrawString(clientFile.FileName, new Font(FontName, 12), Brushes.Black, rectName, format);
                string s = (i < listSourceFile.Length) ? "收件人" : "发件人";
                string info = s + " ID: " + clientFile.ClientID;
                g.DrawString(info, new Font(FontName, 9), Brushes.Gray, rectInfo, format);

                // 计算进度
                float progress = 1.0F * clientFile.Seek / clientFile.Size;
                string state = Miko.CS.Net.Convert.FileStateToString(clientFile.State);
                state += " 进度: " + (progress * 100).ToString("0.00") + " % ";
                state += Miko.CS.Net.Convert.SizeToString(clientFile.Seek) + " / " + Miko.CS.Net.Convert.SizeToString(clientFile.Size);
                g.DrawString(state, new Font(FontName, 9), Brushes.Gray, rectState, format);

                // 绘制文件图标
                int pos = clientFile.FileName.LastIndexOf(".");
                string ext = (pos < 0 || pos == clientFile.FileName.Length - 1) ? "Bin" : clientFile.FileName.Substring(pos + 1);
                if (ext.Length > 3)
                {
                    ext = ext.Substring(0, 3);
                }
                ext = ext.ToUpper();
                byte[] color = BitConverter.GetBytes(ext.GetHashCode());
                g.FillRectangle(new SolidBrush(Color.FromArgb(255, color[2], color[1], color[0])), rectIcon);
                g.DrawString(ext, new Font(FontName, 12), Brushes.White, rectIcon, formatCenter);

                // 绘制进度条
                int progressWidth = (int)(progress * (width - 2 * Blank));
                Brush stateBrush = new SolidBrush(Miko.CS.Net.Convert.FileStateToColor(clientFile.State));
                Rectangle rectProgress = new Rectangle(Blank, pointY + ListHeight - ProgressHeight - Blank + 1, progressWidth, ProgressHeight);
                g.FillRectangle(stateBrush, rectProgress);

                // 检查是否被选中
                if (clientFile.FileID == markedFileID)
                {
                    if ((markedList == FileList.Source && i < listSourceFile.Length) || (markedList == FileList.Target && i >= listSourceFile.Length))
                    {
                        Rectangle rect = new Rectangle(1, pointY + 1, width - 3, ListHeight - 2);
                        g.FillRectangle(new SolidBrush(Color.FromArgb(64, Color.LightGreen)), rect);
                        g.DrawRectangle(Pens.LightGreen, rect);
                    }
                }
            }

            g.Dispose();
            pictureBox1.Size = bitmap.Size;

            Image gc = pictureBox1.Image;
            pictureBox1.Image = bitmap;
            if (gc != null)
            {
                gc.Dispose();
            }
        }
    }
}
